package nautilus.lab.model;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.opengl.Matrix;

public class Coordinator3D {
	private int scaleX, scaleY, scaleZ;
	
	private int viewWidth, viewHeight;
	
	// 0-position
    private int screenX,screenY;
    private Point PX, PY, PZ;
    private Paint paint = new Paint();
    
    private float k = .5f; //this is ratio near/far it  [0.1/1000]
    
    //view matrix
    private float[] viewMatrix = new float[16];
    
    private float[] matrixPerspective = new float[16]; 
    //rotation vector
    private float thetax, thetay, thetaz;
    
    private float dvx = 4.5f, dvy = 4.5f, dvz = 4.5f;
    
    //Perspective projection
    private static float[]PPMatrix={
            1,  0,  0, 0,
            0,  1,  0, 0,
            0,  0,  1, 0,
            0,  0,  -1, 0};
        
    public Coordinator3D(int sx, int sy, int scx, int scy, int scz) {
    	scaleX = scx;
        scaleY = scy;
        scaleZ = scz;
        screenX = sx;
        screenY = sy;
        
        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(2);
        
        Coordinator3D.PPMatrix[9] = 1.0f/(k-1);
        Coordinator3D.PPMatrix[10] = k/(k-1);
        
        Matrix.setLookAtM(viewMatrix, 0, 
        		0.5f, -0.5f, 0.5f, //eye (x,y, z)
        		0, 0, 0,
        		0, 1, 0);
        calculateAxises();
    }
    
    public void onViewChanged(){
    	
    }
        
    public int getScaleX(){
    	return scaleX;
    }
     
    public void setScaleX(int v){
    	scaleX = v;
    }
        
    public int getScaleY() {
    	return scaleY;
    }
       
    public void setScaleY(int v) {
    	scaleY = v;
    }
        
    public int getScaleZ(){
    	return scaleZ;
    }
        
    public void setScaleZ(int v){
    	scaleZ = v;
    }
        
    public int getScreenX(){
    	return screenX;
    }
        
    public void setScreenX(int v){
    	screenX = v;
    }
        
    public int getScreenY(){
    	return screenY;
    }
        
    public void setScreenY(int v){
    	screenY = v;
    }
    
    public void setViewSize(int w, int h){
    	viewWidth = w;
    	viewHeight = h;
    }
        
    public void rotate(float a, float x, float y, float z){
    	thetax = x;
        thetay = y;
        thetaz = z;
        Matrix.rotateM(this.viewMatrix, 0, a,thetax, thetay, thetaz);
        
        /* after rotating, we have to re-calculate the axises on screen */
        calculateAxises();
    }
        
    public void setViewMatrix(float m[]){
    }
        
    public float[] getViewMatrix() {
    	return viewMatrix;
    }
        
    public Coordinator3D(){
    	scaleX = 100;
        scaleY = 100;
        screenX = 200;
        screenY = 70;
    }
        
    public Point world2Screen(float x, float y, float z) {
    	
    	float[] r = new float[4];
        Matrix.multiplyMM(matrixPerspective, 0, PPMatrix, 0, viewMatrix, 0);
        Matrix.multiplyMV(r, 0, matrixPerspective, 0, new float[]{x, y, z, 1}, 0);
    	float xs = r[0] * scaleX + screenX;
    	float ys = screenY - (r[1] * scaleY);
        
        return (new Point( (int)Math.round(xs), (int)Math.round(ys)));
    }
        
        
    public Point world2Screen(float[] p) {
    
        float[] r = new float[4];
        Matrix.multiplyMM(matrixPerspective, 0, PPMatrix, 0, viewMatrix, 0);
        Matrix.multiplyMV(r, 0, matrixPerspective, 0, p, 0);
        float xs = r[0] * scaleX + screenX;
        float ys = screenY - (r[1] * scaleY);
        
        return (new Point( (int)Math.round(xs), (int)Math.round(ys)));
    }
        
    public float[] screen2World(int x, int y, float z){
    	float[] result = new float[3];
        result[0] = (screenX + x)/scaleX;
        result[1] = (screenY - y)/scaleY;
        result[2] = z;
        return result;
    }
        
    public float[] screen2World(Point p, float z) {
    	float[] result = new float[3];
        result[0] = (screenX + p.x)/scaleX;
        result[1] = (screenY - p.y)/scaleY;
        result[2] = z;
        return result;
    }
        
    /* Calculate the SCREEN axises 
    */
    private void calculateAxises() {
    	//world vector for axises
        float[] X = {dvx, 0.0f, 0.0f, 1};
        float[] Y = {0.0f, dvy, 0.0f, 1};
        float[] Z = {0.0f, 0.0f, dvz, 1};
           			//0.0f, 0.0f, 0.0f, 1};
                
        //Matrix.multiplyMM(buffer, 0, viewMatrix, 0, XYZ, 0);
        //Matrix.multiplyMM(buffer, 0, PPMatrix, 0, viewMatrix, 0);
        PX = world2Screen(X);
        PY = world2Screen(Y);
        PZ = world2Screen(Z);
    }
    
    public Point getConner(){
    	return (new Point(screenX, screenY));
    }
    
    public void draw(Canvas c){
    	paint.setColor(Color.RED);
    	c.drawLine(screenX, screenY, PX.x, PX.y, paint);
    	
    	paint.setColor(Color.GREEN);
    	c.drawLine(screenX, screenY, PY.x, PY.y, paint);
    	
    	paint.setColor(Color.BLUE);
    	c.drawLine(screenX, screenY, PZ.x, PZ.y, paint);
    }
}